package com.moon.game.service;

import java.util.LinkedList;

import org.apache.log4j.Logger;

import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import com.moon.game.cache.Memcached;
import com.moon.game.clazz.MsgProto.Msg;
import com.moon.game.constants.Constants;
import com.moon.game.constants.GlobalConstants;
import com.moon.game.util.IDGenerator;
import com.moon.game.vos.MsgVo;
import com.moon.game.vos.PlayerVo;

/**
 * @description 聊天服务
 * @author Ranger 作者 E-mail:haozi000005@163.com
 * @version 创建时间：2012-4-28 下午3:04:16
 */
public class ChatService {
	private static final Logger log = Logger.getLogger(ChatService.class);
	private static LinkedList<MsgVo> worldActChatList = new LinkedList<MsgVo>();
	public static LinkedList<MsgVo> getWorldActChatList() {
		return worldActChatList;
	}
	public static void setWorldActChatList(LinkedList<MsgVo> worldActChatList) {
		ChatService.worldActChatList = worldActChatList;
	}

	private static LinkedList<MsgVo> worldChatList = new LinkedList<MsgVo>();
	
	public static LinkedList<MsgVo> getWorldChatList() {
		return worldChatList;
	}
	public static void setWorldChatList(LinkedList<MsgVo> worldChatList) {
		ChatService.worldChatList = worldChatList;
	}


	/**
	 * 填补公聊信息
	 * 
	 * @param player
	 * @param msg
	 * @return
	 */
	private static MsgVo createPublicMsg(PlayerVo player,String content) {
		MsgVo msg = new MsgVo();
		msg.setContent(content);
		msg.setId(IDGenerator.generateIntId());
		msg.setTime(System.currentTimeMillis());
		if (player != null) {
			msg.setFromSid(player.getSid());
			msg.setFromPlayerId(player.getId());
			msg.setFromPlayerName(player.getName());
			msg.setSex(player.getSex());
		}else {
			msg.setSex(0);
			msg.setFromPlayerName("系统");
		}
		msg.setType(Constants.CHAT_PUBLIC);
		return msg;
	}
	
	
	/**
	 * 发送公聊消息
	 * 
	 * @param player
	 * @param msg
	 */
	public static boolean sendPublicMessage(PlayerVo player,String content) {
		MsgVo message = createPublicMsg(player,content);
		String key = "";
		if (player != null) {
			key = Constants.CHAT_PUBLIC_KEY + player.getLocation();
			log.debug("[" + player.getId() + "]try to send a public message!");
		}else {
			key = Constants.CHAT_WORLD_KEY;
		}
		
		@SuppressWarnings("unchecked")
		LinkedList<byte[]> messages = (LinkedList<byte[]>) Memcached.get(GlobalConstants.POOL_NAME_CHAT, key);
		if (messages == null) {
			messages = new LinkedList<byte[]>();
			messages.addFirst(msgProtoFactory(message));
		}else {
			if (messages.size() > Constants.CHAT_PUBLIC_NUM) {
				messages.removeLast();
			}
			messages.addFirst(msgProtoFactory(message));
		}
		Boolean sendStatu = Memcached.set(GlobalConstants.POOL_NAME_CHAT, key, messages, Constants.CHAT_PUBLIC_DEADLINE);
		if (sendStatu != null && sendStatu) {
			log.debug("[" + player.getId() + "]send a public message succ!");
		}else {
			log.debug("[" + player.getId() + "]send a public message fail!");
		}
		return sendStatu;
	}
	

	/**
	 * 获取公聊消息列表
	 * 
	 * @param mainlandId
	 * @return
	 */
	public static LinkedList<MsgVo> getPublicMessage(int mainlandId) {
		String key = Constants.CHAT_PUBLIC_KEY + mainlandId;
		LinkedList<byte[]> datas = (LinkedList<byte[]>) Memcached.get(GlobalConstants.POOL_NAME_CHAT, key);
		LinkedList<MsgVo> messages = new LinkedList<MsgVo>();
		if (datas != null) {
			for (byte[] d : datas) {
				messages.addLast(msgVoFactory(d));
			}
		}
		return messages;
	}
	
	/**
	 * 填补世界聊天信息
	 * 
	 * @param player
	 * @param content
	 * @param isAct是否是动态，true是，false不是
	 * @return
	 */
	private static MsgVo createWorldMsg(PlayerVo player,String content, boolean isAct) {
		MsgVo msg = new MsgVo();
		msg.setContent(content);
		msg.setId(IDGenerator.generateIntId());
		msg.setTime(System.currentTimeMillis());
		if (player != null) {
			msg.setFromSid(player.getSid());
			msg.setFromPlayerId(player.getId());
			msg.setSex(player.getSex());
			msg.setFromPlayerName(player.getName());
		}else {
			msg.setSex(0);
			msg.setFromPlayerName("系统");
		}
		if (isAct) {
			msg.setType(Constants.CHAT_WORLD_ACT);
		}else {
			msg.setType(Constants.CHAT_WORLD);
		}
		return msg;
	}
	
	
	/**
	 * 发送公聊消息
	 * 
	 * @param player
	 * @param msg
	 */
	public static boolean sendWorldMessage(PlayerVo player,String content) {
		MsgVo message = createWorldMsg(player, content, false);
		if (player != null) {
			log.debug("[" + player.getId() + "]try to send world messsage!");
		}
		String key = Constants.CHAT_WORLD_KEY;
		@SuppressWarnings("unchecked")
		LinkedList<byte[]> messages = (LinkedList<byte[]>) Memcached.get(GlobalConstants.POOL_NAME_CHAT, key);
		if (messages == null) {
			messages = new LinkedList<byte[]>();
			messages.addFirst(msgProtoFactory(message));
		}else {
			if (messages.size() > Constants.CHAT_WORLD_NUM) {
				messages.removeLast();
			}
			messages.addFirst(msgProtoFactory(message));
		}
		Boolean sendStatu = Memcached.set(GlobalConstants.POOL_NAME_CHAT, key, messages, Constants.CHAT_WORLD_DEADLINE);
		if (player != null) {
			if (sendStatu != null && sendStatu) {
				log.debug("[" + player.getId() + "]send world messsage succ!");
			}else {
				log.debug("[" + player.getId() + "]send world messsage fail!");
			}
		}
		return sendStatu;
	}
	
	
	/**
	 * 发送世界动态消息
	 * 
	 * @param player
	 * @param msg
	 */
	public static boolean sendWorldActMessage(PlayerVo player,String content) {
		MsgVo message = createWorldMsg(player, content, true);
		if (player != null) {
			log.debug("[" + player.getId() + "]try to send world messsage!");
		}
		String key = Constants.CHAT_WORLD_ACT_KEY;
		@SuppressWarnings("unchecked")
		LinkedList<byte[]> messages = (LinkedList<byte[]>) Memcached.get(GlobalConstants.POOL_NAME_CHAT, key);
		if (messages == null) {
			messages = new LinkedList<byte[]>();
			messages.addFirst(msgProtoFactory(message));
		}else {
			if (messages.size() > Constants.CHAT_ACT_PRIVATE_NUM) {
				messages.removeLast();
			}
			messages.addFirst(msgProtoFactory(message));
		}
		Boolean sendStatu = Memcached.set(GlobalConstants.POOL_NAME_CHAT, key, messages, Constants.CHAT_WORLD_DEADLINE);
		if (player != null) {
			if (sendStatu != null && sendStatu) {
				log.debug("[" + player.getId() + "]send world act messsage succ!");
			}else {
				log.debug("[" + player.getId() + "]send world act messsage fail!");
			}
		}
		return sendStatu;
	}
	
	/**
	 * 发送私聊消息
	 * 
	 * @param fromPlayer
	 * @param toPlayerId
	 * @param message
	 * @param save是否保存到自己内存
	 */
	public static void sendPrivateMessage(PlayerVo fromPlayer, String toPlayerId, String toPlayerName, String content, boolean save) {
		MsgVo message = createPrivateMsg(fromPlayer,content,toPlayerId, toPlayerName, null, false, null);
		
		//发送到对方memcached
		String key = Constants.CHAT_PRIVATE_KEY + toPlayerId;
		@SuppressWarnings("unchecked")
		LinkedList<byte[]> messages = (LinkedList<byte[]>) Memcached.get(GlobalConstants.POOL_NAME_CHAT, key);
		if (messages == null) {
			messages = new LinkedList<byte[]>();
			messages.addFirst(msgProtoFactory(message));
		}else {
			if (messages.size() > Constants.CHAT_PRIVATE_NUM) {
				messages.removeLast();
			}
			messages.addFirst(msgProtoFactory(message));
		}
		Memcached.set(GlobalConstants.POOL_NAME_CHAT, key, messages, Constants.CHAT_PRIVATE_DEADLINE);
		
		if (fromPlayer != null && save) {
			//存到自己的memcached
			key = Constants.CHAT_PRIVATE_KEY + fromPlayer.getId();
			@SuppressWarnings("unchecked")
			LinkedList<byte[]> myMessages = (LinkedList<byte[]>) Memcached.get(GlobalConstants.POOL_NAME_CHAT, key);
			if (myMessages == null) {
				myMessages = new LinkedList<byte[]>();
				myMessages.addFirst(msgProtoFactory(message));
			}else {
				if (myMessages.size() > Constants.CHAT_PRIVATE_NUM) {
					myMessages.removeLast();
				}
				myMessages.addFirst(msgProtoFactory(message));
			}
			Memcached.set(GlobalConstants.POOL_NAME_CHAT, key, myMessages, Constants.CHAT_PRIVATE_DEADLINE);
		}
	}
	
	/**
	 * 发送私聊动态消息
	 * 
	 * @param fromPlayer
	 * @param toPlayerId
	 * @param toPlayerName
	 * @param content
	 * @param cmd
	 * @param par 保留字段，存放额外信息
	 */
	public static void sendPrivateActMessage(PlayerVo fromPlayer, String toPlayerId, String toPlayerName, String content, String cmd, String par) {
		MsgVo message = createPrivateMsg(fromPlayer,content,toPlayerId, toPlayerName, cmd, true, par);
		//发送到对方memcached
		String key = Constants.CHAT_PRIVATE_ACT_KEY + toPlayerId;
		@SuppressWarnings("unchecked")
		LinkedList<byte[]> messages = (LinkedList<byte[]>) Memcached.get(GlobalConstants.POOL_NAME_CHAT, key);
		if (messages == null) {
			messages = new LinkedList<byte[]>();
		}else {
			if (messages.size() > Constants.CHAT_ACT_PRIVATE_NUM) {
				messages.removeLast();
			}
		}
		LinkedList<byte[]> newMessages = mergeTheSameActMsg(message, messages);
		Memcached.set(GlobalConstants.POOL_NAME_CHAT, key, newMessages, Constants.CHAT_PRIVATE_DEADLINE);
	}
	
	/**
	 * 合并需要合并的动态
	 * 
	 * @param msg
	 * @param datas
	 * @return
	 */
	private static LinkedList<byte[]> mergeTheSameActMsg(MsgVo msg, LinkedList<byte[]> datas) {
		LinkedList<byte[]> messages = new LinkedList<byte[]>();
		if (datas != null && datas.size() > 0) {
			for (byte[] d : datas) {
				MsgVo vo = msgVoFactory(d);
				if (msg.getCmd() != null && msg.getPar() != null && vo.getCmd() != null && vo.getPar() != null
						&& msg.getCmd().equals(vo.getCmd()) && msg.getPar().equals(vo.getPar())) {
					//此种情况有必要合并
					messages.addFirst(msgProtoFactory(msg));
					continue;
				}
				messages.addLast(msgProtoFactory(vo));
			}
		}else {
			messages.addFirst(msgProtoFactory(msg));
		}
		return messages;
	}
	
	/**
	 * 删除指定动态消息
	 * 
	 * @param fromPlayer
	 * @param toPlayerId
	 * @param message
	 */
	public static void removeThePrivateActMessage(String playerId, int msgId) {
		//发送到对方memcached
		String key = Constants.CHAT_PRIVATE_ACT_KEY + playerId;
		@SuppressWarnings("unchecked")
		LinkedList<byte[]> messages = (LinkedList<byte[]>) Memcached.get(GlobalConstants.POOL_NAME_CHAT, key);
		if (messages != null) {
			LinkedList<byte[]> newMessages = new LinkedList<byte[]>();
			for (byte[] data : messages) {
				MsgVo vo = msgVoFactory(data);
				if (vo.getId() == msgId) {
					continue;
				}
				newMessages.addFirst(data);
			}
			Memcached.set(GlobalConstants.POOL_NAME_CHAT, key, newMessages, Constants.CHAT_PRIVATE_DEADLINE);
		}
	}	
	
	/**
	 * 根据cmd和par来删除指定动态消息
	 * 
	 * @param playerId
	 * @param cmd
	 * @param par
	 */
	public static void removeThePrivateActMessage(String playerId, String cmd, String par) {
		//发送到对方memcached
		String key = Constants.CHAT_PRIVATE_ACT_KEY + playerId;
		if (cmd == null) {
			return;
		}
		@SuppressWarnings("unchecked")
		LinkedList<byte[]> messages = (LinkedList<byte[]>) Memcached.get(GlobalConstants.POOL_NAME_CHAT, key);
		if (messages != null) {
			LinkedList<byte[]> newMessages = new LinkedList<byte[]>();
			for (byte[] data : messages) {
				MsgVo vo = msgVoFactory(data);
				if (cmd.equals(vo.getCmd())) {
					if (par == null || par.equals(vo.getPar())) {
						continue;
					}
				}
				newMessages.addFirst(data);
			}
			Memcached.set(GlobalConstants.POOL_NAME_CHAT, key, newMessages, Constants.CHAT_PRIVATE_DEADLINE);
		}
	}	
	
	/**
	 * 填补世界聊天信息
	 * 
	 * @param player
	 * @param content
	 * @param toPlayerId
	 * @param toPlayerName
	 * @param cmd
	 * @param isAct是否是动态消息true是，false不是
	 * @return
	 */
	private static MsgVo createPrivateMsg(PlayerVo player,String content, String toPlayerId, String toPlayerName, String cmd, boolean isAct, String par) {
		MsgVo msg = new MsgVo();
		msg.setContent(content);
		msg.setCmd(cmd);
		msg.setId(IDGenerator.generateIntId());
		msg.setTime(System.currentTimeMillis());
		msg.setPar(par);
		if (player != null) {
			msg.setFromSid(player.getSid());
			msg.setFromPlayerId(player.getId());
			msg.setFromPlayerName(player.getName());
			msg.setSex(player.getSex());
		}else {
			msg.setSex(0);
			msg.setFromPlayerName("系统");
		}
		if (isAct) {
			msg.setType(Constants.CHAT_PRIVATE_ACT);
		}else {
			msg.setType(Constants.CHAT_PRIVATE);
		}
		msg.setToPlayerId(toPlayerId);
		if (toPlayerName == null || toPlayerName.length() == 0) {
			msg.setToPlayerName("");
		}else {
			msg.setToPlayerName(toPlayerName);
		}
		return msg;
	}
	
	/**
	 * 获取私聊信息
	 * 
	 * @param playerId
	 * @return
	 */
	public static LinkedList<MsgVo> getPrivateMessage(String playerId) {
		String key = Constants.CHAT_PRIVATE_KEY + playerId;
		LinkedList<byte[]> datas = (LinkedList<byte[]>) Memcached.get(GlobalConstants.POOL_NAME_CHAT, key);
		LinkedList<MsgVo> messages = new LinkedList<MsgVo>();
		if (datas != null) {
			for (byte[] d : datas) {
				messages.addLast(msgVoFactory(d));
			}
		}
		return messages;
	}
	
	/**
	 * 获取私聊动态信息
	 * 
	 * @param playerId
	 * @return
	 */
	public static LinkedList<MsgVo> getPrivateActMessage(String playerId) {
		String key = Constants.CHAT_PRIVATE_ACT_KEY + playerId;
		LinkedList<byte[]> datas = (LinkedList<byte[]>) Memcached.get(GlobalConstants.POOL_NAME_CHAT, key);
		LinkedList<MsgVo> messages = new LinkedList<MsgVo>();
		if (datas != null) {
			for (byte[] d : datas) {
				messages.addLast(msgVoFactory(d));
			}
		}
		return messages;
	}
	
	/**
	 * msg mem2byte[]
	 * 
	 * @param msgVo
	 * @return
	 */
	public static byte[] msgProtoFactory(MsgVo msgVo) {
		Msg.Builder msg = Msg.newBuilder();
		msg.setId(msgVo.getId());
		msg.setSex(msgVo.getSex());
		if (msgVo.getFromSid() != null) {
			msg.setFromSid(msgVo.getFromSid());
		}
		if (msgVo.getFromPlayerId() != null) {
			msg.setFromPlayerId(msgVo.getFromPlayerId());
		}
		if (msgVo.getFromPlayerName() != null) {
			msg.setFromPlayerName(msgVo.getFromPlayerName());
		}
		if (msgVo.getToPlayerId() != null) {
			msg.setToPlayerId(msgVo.getToPlayerId());
		}
		if (msgVo.getToPlayerName() != null) {
			msg.setToPlayerName(msgVo.getToPlayerName());
		}
		msg.setType(msgVo.getType());
		msg.setSubType(msgVo.getSubType());
		msg.setTime(msgVo.getTime());
		if (msgVo.getContent() != null) {
			msg.setContent(msgVo.getContent());
		}
		if (msgVo.getCmd() != null) {
			msg.setCmd(msgVo.getCmd());
		}
		if (msgVo.getPar() != null) {
			msg.setPar(msgVo.getPar());
		}
		return msg.build().toByteString().toByteArray();
	}
	
	/**
	 * msg byte[]2mem
	 * 
	 * @param msgString
	 * @return
	 */
	public static MsgVo msgVoFactory(byte[] msgString) {
		Msg msg = null;
		try {
			msg = Msg.parseFrom(ByteString.copyFrom(msgString));
		} catch (InvalidProtocolBufferException e) {
			e.printStackTrace();
		}
		
		if (msg != null) {
			MsgVo msgVo = new MsgVo();
			msgVo.setId(msg.getId());
			msgVo.setSex(msg.getSex());
			if (msg.hasFromSid()) {
				msgVo.setFromSid(msg.getFromSid());
			}
			if (msg.hasFromPlayerId()) {
				msgVo.setFromPlayerId(msg.getFromPlayerId());
			}
			if (msg.hasFromPlayerName()) {
				msgVo.setFromPlayerName(msg.getFromPlayerName());
			}
			if (msg.hasToPlayerId()) {
				msgVo.setToPlayerId(msg.getToPlayerId());
			}
			if (msg.hasToPlayerName()) {
				msgVo.setToPlayerName(msg.getToPlayerName());
			}
			msgVo.setType(msg.getType());
			msgVo.setSubType(msg.getSubType());
			msgVo.setTime(msg.getTime());
			if (msg.hasContent()) {
				msgVo.setContent(msg.getContent());
			}
			if (msg.hasCmd()) {
				msgVo.setCmd(msg.getCmd());
			}
			if (msg.hasPar()) {
				msgVo.setPar(msg.getPar());
			}
			return msgVo;
		}
		return null;
	}
}
